use derive_builder::Builder;
use serde::{Deserialize, Serialize};

use crate::error::Error;
use crate::mapper::ValueMapper;
use crate::modeling::{
    Class, ClassAttributeBuilder, ClassBuilder, ClassGetter, ClassRelationBuilder,
    RelationRelatedType, ValueType,
};
use crate::modeling::{
    ClassAttributePersistence, ClassPersistence, ClassPersistenceBuilder, ClassPersistenceGetter,
    ClassRelation, ClassRelationGetter, Value,
};

use super::ApplicationConversation;

const APPLICATION_CONVERSATION_MESSAGE_CLASS_IDENTIFIER: &'static str =
    "g01_application_conversation_message";

const APPLICATION_CONVERSATION_MESSAGE_CLASS_NAME: &'static str =
    "application_conversation_message";

const APPLICATION_CONVERSATION_MESSAGE_TABLE_NAME: &'static str =
    "_g01_application_conversation_messages";

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum ApplicationConversationMessageStatus {
    /// Agent
    #[default]
    #[serde(rename = "normal")]
    Normal,
}

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "ApplicationConversationMessageBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct ApplicationConversationMessage {
    /// id
    pub id: i64,
    /// conversation_identifier
    pub conversation_identifier: String,
    /// identifier
    pub identifier: String,
    /// identifier
    pub parent_identifier: Option<String>,
    /// 输入
    pub inputs: Option<String>,
    /// query
    pub query: String,
    /// answer
    pub answer: String,
    /// files
    pub files: Option<String>,
    //
    pub feedback: Option<String>,
    /// retriever_resources
    pub retriever_resources: Option<String>,
    /// 类型
    pub status: ApplicationConversationMessageStatus,
    /// 创建时间
    pub created_at: i64,
    /// 更新时间
    pub updated_at: i64,
}

//
crate::impl_from_value!(ApplicationConversationMessage);
crate::impl_class_persistence_getter!(
    ApplicationConversationMessage,
    APPLICATION_CONVERSATION_MESSAGE_TABLE_NAME
);
crate::impl_class_relations_getter!(
    ApplicationConversationMessage,
    vec![
        ClassRelationBuilder::default()
            .src_identifier(ApplicationConversation::get_identifier()?)
            .target_identifier(Self::get_identifier()?)
            .related_type(RelationRelatedType::Keys)
            .related_at("conversation_identifier")
            .build()?,
        ClassRelationBuilder::default()
            .src_identifier(ApplicationConversationMessage::get_identifier()?)
            .target_identifier(Self::get_identifier()?)
            .related_type(RelationRelatedType::Keys)
            .related_at("parent_identifier")
            .build()?,
    ]
);

impl ClassGetter for ApplicationConversationMessage {
    fn get_name() -> anyhow::Result<String> {
        Ok(String::from(APPLICATION_CONVERSATION_MESSAGE_CLASS_NAME))
    }
    fn get_identifier() -> anyhow::Result<String> {
        Ok(String::from(
            APPLICATION_CONVERSATION_MESSAGE_CLASS_IDENTIFIER,
        ))
    }
    fn get_class() -> anyhow::Result<Class> {
        let mut attribute_builder = ClassAttributeBuilder::default();
        attribute_builder.class_identifier(APPLICATION_CONVERSATION_MESSAGE_CLASS_IDENTIFIER);

        let mut commons = crate::modeling::simple_attributes_with_builder(&attribute_builder)?;
        let mut append = vec![
            attribute_builder
                .clone()
                .name("conversation_identifier")
                .title("应用")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("identifier")
                .title("类型")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("parent_identifier")
                .title("类型")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("query")
                .title("问")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("answer")
                .title("答")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("status")
                .title("状态")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("files")
                .title("文件")
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("feedback")
                .title("反馈")
                .data_type(ValueType::String)
                .build()?,
        ];
        append.append(&mut commons);
        append.sort_by(|a, b| a.position.cmp(&b.position));

        let clazz = ClassBuilder::default()
            .identifier(APPLICATION_CONVERSATION_MESSAGE_CLASS_IDENTIFIER)
            .name(APPLICATION_CONVERSATION_MESSAGE_CLASS_NAME)
            .data_is_type(true)
            .is_persistent(true)
            .primary_key(String::from("identifier"))
            .attributes(append)
            .build()?;
        Ok(clazz)
    }
}
